package com.ysy.tz.core.validator;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;

public class Validator {
    private Map<Check, ChangeListener<ValidationResult>> checks = new LinkedHashMap();
    private ReadOnlyObjectWrapper<ValidationResult> validationResultProperty = new ReadOnlyObjectWrapper(new ValidationResult());
    private ReadOnlyBooleanWrapper containsWarningsProperty = new ReadOnlyBooleanWrapper();
    private ReadOnlyBooleanWrapper containsErrorsProperty = new ReadOnlyBooleanWrapper();

    public Validator() {
    }

    public Check createCheck() {
        Check check = new Check();
        this.add(check);
        return check;
    }

    public void add(Check check) {
        ChangeListener<ValidationResult> listener = (obs, oldv, newv) -> {
            this.refreshProperties();
        };
        this.checks.put(check, listener);
        check.validationResultProperty().addListener(listener);
    }

    public void remove(Check check) {
        ChangeListener<ValidationResult> listener = (ChangeListener)this.checks.remove(check);
        if (listener != null) {
            check.validationResultProperty().removeListener(listener);
        }

        this.refreshProperties();
    }

    public ValidationResult getValidationResult() {
        return (ValidationResult)this.validationResultProperty.get();
    }

    public ReadOnlyObjectProperty<ValidationResult> validationResultProperty() {
        return this.validationResultProperty.getReadOnlyProperty();
    }

    public ReadOnlyBooleanProperty containsWarningsProperty() {
        return this.containsWarningsProperty.getReadOnlyProperty();
    }

    public boolean containsWarnings() {
        return this.containsWarningsProperty().get();
    }

    public ReadOnlyBooleanProperty containsErrorsProperty() {
        return this.containsErrorsProperty.getReadOnlyProperty();
    }

    public boolean containsErrors() {
        return this.containsErrorsProperty().get();
    }

    public boolean validate() {
        Iterator var1 = this.checks.keySet().iterator();

        while(var1.hasNext()) {
            Check check = (Check)var1.next();
            check.recheck();
        }

        return !this.containsErrors();
    }

    private void refreshProperties() {
        ValidationResult nextResult = new ValidationResult();
        Iterator var2 = this.checks.keySet().iterator();

        while(var2.hasNext()) {
            Check check = (Check)var2.next();
            nextResult.addAll(check.getValidationResult().getMessages());
        }

        this.validationResultProperty.set(nextResult);
        boolean hasWarnings = false;
        boolean hasErrors = false;

        ValidationMessage msg;
        for(Iterator var4 = nextResult.getMessages().iterator(); var4.hasNext(); hasErrors = hasErrors || msg.getSeverity() == Severity.ERROR) {
            msg = (ValidationMessage)var4.next();
            hasWarnings = hasWarnings || msg.getSeverity() == Severity.WARNING;
        }

        this.containsWarningsProperty.set(hasWarnings);
        this.containsErrorsProperty.set(hasErrors);
    }

    public StringBinding createStringBinding() {
        return this.createStringBinding("• ", "\n", Severity.ERROR);
    }

    public StringBinding createStringBinding(String prefix, String separator, Severity... severities) {
        Set<Severity> wanted = new HashSet(Arrays.asList(severities));
        if (wanted.isEmpty()) {
            wanted.add(Severity.ERROR);
        }

        return Bindings.createStringBinding(() -> {
            StringBuilder str = new StringBuilder();
            Iterator var5 = ((ValidationResult)this.validationResultProperty.get()).getMessages().iterator();

            while(var5.hasNext()) {
                ValidationMessage msg = (ValidationMessage)var5.next();
                if (wanted.contains(msg.getSeverity())) {
                    if (str.length() > 0) {
                        str.append(separator);
                    }

                    str.append(prefix + msg.getText());
                }
            }

            return str.toString();
        }, new Observable[]{this.validationResultProperty});
    }
}
